home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
- /* shk.c - version 1.0.3 */
-
- #include "hack.h"
- #ifdef QUEST
- int shlevel = 0;
- struct monst *shopkeeper = 0;
- struct obj *billobjs = 0;
- obfree(obj,merge) register struct obj *obj, *merge; {
- free((char *) obj);
- }
- inshop(){ return(0); }
- addtobill(){}
- subfrombill(){}
- splitbill(){}
- dopay(){ return(0); }
- paybill(){}
- doinvbill(){ return(0); }
- shkdead(){}
- shkcatch(){ return(0); }
- shk_move(){ return(0); }
- replshk(mtmp,mtmp2) struct monst *mtmp, *mtmp2; {}
- char *shkname(){ return(""); }
-
- #else QUEST
- #include "mfndpos.h"
- #include "mkroom.h"
- #include "eshk.h"
-
- #define ESHK(mon) ((struct eshk *)(&(mon->mextra[0])))
- #define NOTANGRY(mon) mon->mpeaceful
- #define ANGRY(mon) !NOTANGRY(mon)
-
- extern char plname[], *xname();
- extern struct obj *o_on(), *bp_to_obj();
-
- /* Descriptor of current shopkeeper. Note that the bill need not be
- per-shopkeeper, since it is valid only when in a shop. */
- struct monst *shopkeeper = 0;
- struct bill_x *bill;
- int shlevel = 0; /* level of this shopkeeper */
- struct obj *billobjs; /* objects on bill with bp->useup */
- /* only accessed here and by save & restore */
- long int total; /* filled by addupbill() */
- long int followmsg; /* last time of follow message */
-
- /*
- invariants: obj->unpaid iff onbill(obj) [unless bp->useup]
- obj->quan <= bp->bquan
- */
-
-
- char shtypes[] = { /* 8 shoptypes: 7 specialized, 1 mixed */
- RING_SYM, WAND_SYM, WEAPON_SYM, FOOD_SYM, SCROLL_SYM,
- POTION_SYM, ARMOR_SYM, 0
- };
-
- char *shopnam[] = {
- "engagement ring", "walking cane", "antique weapon",
- "delicatessen", "second hand book", "liquor",
- "used armor", "assorted antiques"
- };
-
- char *
- shkname(mtmp) /* called in do_name.c */
- register struct monst *mtmp;
- {
- return(ESHK(mtmp)->shknam);
- }
-
- shkdead(mtmp) /* called in mon.c */
- register struct monst *mtmp;
- {
- register struct eshk *eshk = ESHK(mtmp);
-
- if(eshk->shoplevel == dlevel)
- rooms[eshk->shoproom].rtype = 0;
- if(mtmp == shopkeeper) {
- setpaid();
- shopkeeper = 0;
- bill = (struct bill_x *) -1000; /* dump core when referenced */
- }
- }
-
- replshk(mtmp,mtmp2)
- register struct monst *mtmp, *mtmp2;
- {
- if(mtmp == shopkeeper) {
- shopkeeper = mtmp2;
- bill = &(ESHK(shopkeeper)->bill[0]);
- }
- }
-
- setpaid(){ /* caller has checked that shopkeeper exists */
- /* either we paid or left the shop or he just died */
- register struct obj *obj;
- register struct monst *mtmp;
- for(obj = invent; obj; obj = obj->nobj)
- obj->unpaid = 0;
- for(obj = fobj; obj; obj = obj->nobj)
- obj->unpaid = 0;
- for(obj = fcobj; obj; obj = obj->nobj)
- obj->unpaid = 0;
- for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
- for(obj = mtmp->minvent; obj; obj = obj->nobj)
- obj->unpaid = 0;
- for(mtmp = fallen_down; mtmp; mtmp = mtmp->nmon)
- for(obj = mtmp->minvent; obj; obj = obj->nobj)
- obj->unpaid = 0;
- while(obj = billobjs){
- billobjs = obj->nobj;
- free((char *) obj);
- }
- ESHK(shopkeeper)->billct = 0;
- }
-
- addupbill(){ /* delivers result in total */
- /* caller has checked that shopkeeper exists */
- register ct = ESHK(shopkeeper)->billct;
- register struct bill_x *bp = bill;
- total = 0;
- while(ct--){
- total += bp->price * bp->bquan;
- bp++;
- }
- }
-
- inshop(){
- register roomno = inroom(u.ux,u.uy);
-
- /* Did we just leave a shop? */
- if(u.uinshop &&
- (u.uinshop != roomno + 1 || shlevel != dlevel || !shopkeeper)) {
- #ifdef DGK
- /* This is part of the bugfix for shopkeepers not having their
- * bill paid. As reported by ab@unido -dgk
- */
- if(shopkeeper) {
- if(ESHK(shopkeeper)->billct) {
- if (inroom(shopkeeper->mx, shopkeeper->my) ==
- u.uinshop - 1)
- pline("Somehow you escaped the shop without paying!");
- addupbill();
- pline("You stole for a total worth of %ld zorkmids.",
- total);
- ESHK(shopkeeper)->robbed += total;
- setpaid();
- if((rooms[ESHK(shopkeeper)->shoproom].rtype == GENERAL)
- == (rn2(3) == 0))
- ESHK(shopkeeper)->following = 1;
- }
- shopkeeper = 0;
- shlevel = 0;
- }
- u.uinshop = 0;
- #else
- u.uinshop = 0;
- if(shopkeeper) {
- if(ESHK(shopkeeper)->billct) {
- pline("Somehow you escaped the shop without paying!");
- addupbill();
- pline("You stole for a total worth of %ld zorkmids.",
- total);
- ESHK(shopkeeper)->robbed += total;
- setpaid();
- if((rooms[ESHK(shopkeeper)->shoproom].rtype == GENERAL)
- == (rn2(3) == 0))
- ESHK(shopkeeper)->following = 1;
- }
- shopkeeper = 0;
- shlevel = 0;
- }
- #endif DGK
- }
-
- /* Did we just enter a zoo of some kind? */
- if(roomno >= 0) {
- register int rt = rooms[roomno].rtype;
- register struct monst *mtmp;
- if(rt == ZOO) {
- pline("Welcome to David's treasure zoo!");
- } else
- if(rt == SWAMP) {
- pline("It looks rather muddy down here.");
- } else
- if(rt == MORGUE) {
- if(midnight())
- pline("Go away! Go away!");
- else
- pline("You get an uncanny feeling ...");
- } else
- rt = 0;
- if(rt != 0) {
- rooms[roomno].rtype = 0;
- for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
- if(rt != ZOO || !rn2(3))
- mtmp->msleep = 0;
- }
- }
-
- /* Did we just enter a shop? */
- if(roomno >= 0 && rooms[roomno].rtype >= 8) {
- if(shlevel != dlevel || !shopkeeper
- || ESHK(shopkeeper)->shoproom != roomno)
- findshk(roomno);
- if(!shopkeeper) {
- rooms[roomno].rtype = 0;
- u.uinshop = 0;
- #ifndef DGK
- /* This is part of the bugfix for shopkeepers not having their
- * bill paid. As reported by ab@unido -dgk
- */
- } else if(inroom(shopkeeper->mx, shopkeeper->my) != roomno) {
- u.uinshop = 0;
- #endif DGK
- } else if(!u.uinshop){
- if(!ESHK(shopkeeper)->visitct ||
- strncmp(ESHK(shopkeeper)->customer, plname, PL_NSIZ)){
-
- /* He seems to be new here */
- ESHK(shopkeeper)->visitct = 0;
- ESHK(shopkeeper)->following = 0;
- (void) strncpy(ESHK(shopkeeper)->customer,plname,PL_NSIZ);
- NOTANGRY(shopkeeper) = 1;
- }
- if(!ESHK(shopkeeper)->following) {
- boolean box, pick;
-
- pline("Hello %s! Welcome%s to %s's %s shop!",
- plname,
- ESHK(shopkeeper)->visitct++ ? " again" : "",
- shkname(shopkeeper),
- shopnam[rooms[ESHK(shopkeeper)->shoproom].rtype - 8] );
- box = carrying(ICE_BOX);
- pick = carrying(PICK_AXE);
- if(box || pick) {
- if(dochug(shopkeeper)) {
- u.uinshop = 0; /* he died moving */
- return(0);
- }
- pline("Will you please leave your %s outside?",
- (box && pick) ? "box and pick-axe" :
- box ? "box" : "pick-axe");
- }
- }
- u.uinshop = roomno + 1;
- }
- }
- return(u.uinshop);
- }
-
- findshk(roomno)
- register roomno;
- {
- register struct monst *mtmp;
- for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
- if(mtmp->isshk && ESHK(mtmp)->shoproom == roomno
- && ESHK(mtmp)->shoplevel == dlevel) {
- shopkeeper = mtmp;
- bill = &(ESHK(shopkeeper)->bill[0]);
- shlevel = dlevel;
- if(ANGRY(shopkeeper) &&
- strncmp(ESHK(shopkeeper)->customer,plname,PL_NSIZ))
- NOTANGRY(shopkeeper) = 1;
- /* billobjs = 0; -- this is wrong if we save in a shop */
- /* (and it is harmless to have too many things in billobjs) */
- return;
- }
- shopkeeper = 0;
- shlevel = 0;
- bill = (struct bill_x *) -1000; /* dump core when referenced */
- }
-
- struct bill_x *
- onbill(obj) register struct obj *obj; {
- register struct bill_x *bp;
- if(!shopkeeper) return(0);
- for(bp = bill; bp < &bill[ESHK(shopkeeper)->billct]; bp++)
- if(bp->bo_id == obj->o_id) {
- if(!obj->unpaid) pline("onbill: paid obj on bill?");
- return(bp);
- }
- if(obj->unpaid) pline("onbill: unpaid obj not on bill?");
- return(0);
- }
-
- /* called with two args on merge */
- obfree(obj,merge) register struct obj *obj, *merge; {
- register struct bill_x *bp = onbill(obj);
- register struct bill_x *bpm;
- if(bp) {
- if(!merge){
- bp->useup = 1;
- obj->unpaid = 0; /* only for doinvbill */
- obj->nobj = billobjs;
- billobjs = obj;
- return;
- }
- bpm = onbill(merge);
- if(!bpm){
- /* this used to be a rename */
- impossible("obfree: not on bill??");
- return;
- } else {
- /* this was a merger */
- bpm->bquan += bp->bquan;
- ESHK(shopkeeper)->billct--;
- *bp = bill[ESHK(shopkeeper)->billct];
- }
- }
- free((char *) obj);
- }
-
- pay(tmp,shkp)
- long tmp;
- register struct monst *shkp;
- {
- long robbed = ESHK(shkp)->robbed;
-
- u.ugold -= tmp;
- shkp->mgold += tmp;
- flags.botl = 1;
- if(robbed) {
- robbed -= tmp;
- if(robbed < 0) robbed = 0;
- ESHK(shkp)->robbed = robbed;
- }
- }
-